#include <gtk/gtklistbox.h>
#include "recording.h"
+#include "rendernodeview.h"
#include "renderrecording.h"
struct _GtkInspectorRecorderPrivate
{
- GListStore *recordings;
+ GListModel *recordings;
GtkWidget *recordings_list;
+ GtkWidget *render_node_view;
};
G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorRecorder, gtk_inspector_recorder, GTK_TYPE_BIN)
+static void
+recordings_list_row_selected (GtkListBox *box,
+ GtkListBoxRow *row,
+ GtkInspectorRecorder *recorder)
+{
+ GtkInspectorRecorderPrivate *priv = gtk_inspector_recorder_get_instance_private (recorder);
+ GtkInspectorRecording *recording;
+
+ if (row)
+ {
+ recording = g_list_model_get_item (priv->recordings, gtk_list_box_row_get_index (row));
+
+ gtk_render_node_view_set_render_node (GTK_RENDER_NODE_VIEW (priv->render_node_view),
+ gtk_inspector_render_recording_get_node (GTK_INSPECTOR_RENDER_RECORDING (recording)));
+ gtk_render_node_view_set_clip_region (GTK_RENDER_NODE_VIEW (priv->render_node_view),
+ gtk_inspector_render_recording_get_clip_region (GTK_INSPECTOR_RENDER_RECORDING (recording)));
+ }
+ else
+ {
+ gtk_render_node_view_set_render_node (GTK_RENDER_NODE_VIEW (priv->render_node_view), NULL);
+ }
+}
+
static GtkWidget *
gtk_inspector_recorder_recordings_list_create_widget (gpointer item,
gpointer user_data)
G_OBJECT_CLASS (gtk_inspector_recorder_parent_class)->constructed (object);
gtk_list_box_bind_model (GTK_LIST_BOX (priv->recordings_list),
- G_LIST_MODEL (priv->recordings),
+ priv->recordings,
gtk_inspector_recorder_recordings_list_create_widget,
NULL,
NULL);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorRecorder, recordings);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorRecorder, recordings_list);
+ gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorRecorder, render_node_view);
+
+ gtk_widget_class_bind_template_callback (widget_class, recordings_list_row_selected);
}
static void
gdk_window_get_height (window) },
region,
node);
- g_list_store_append (priv->recordings, recording);
+ g_list_store_append (G_LIST_STORE (priv->recordings), recording);
g_object_unref (recording);
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "rendernodeview.h"
+
+#include <cairo-gobject.h>
+#include <glib/gi18n-lib.h>
+#include <math.h>
+
+#include "gsk/gskrendernodeprivate.h"
+#include "gtkwidgetprivate.h"
+
+#include "fallback-c89.c"
+
+typedef struct _GtkRenderNodeViewPrivate GtkRenderNodeViewPrivate;
+struct _GtkRenderNodeViewPrivate
+{
+ GdkRectangle viewport;
+ GskRenderNode *render_node;
+ cairo_region_t *clip_region;
+};
+
+enum
+{
+ PROP_0,
+ PROP_VIEWPORT,
+ PROP_RENDER_NODE,
+ PROP_CLIP_REGION,
+ LAST_PROP
+};
+
+static GParamSpec *props[LAST_PROP] = { NULL, };
+
+G_DEFINE_TYPE_WITH_PRIVATE (GtkRenderNodeView, gtk_render_node_view, GTK_TYPE_WIDGET)
+
+static gboolean
+gtk_render_node_view_has_viewport (GtkRenderNodeView *view)
+{
+ GtkRenderNodeViewPrivate *priv = gtk_render_node_view_get_instance_private (view);
+
+ return priv->viewport.width > 0
+ && priv->viewport.height > 0;
+}
+
+static void
+gtk_render_node_view_get_effective_viewport (GtkRenderNodeView *view,
+ GdkRectangle *viewport)
+{
+ GtkRenderNodeViewPrivate *priv = gtk_render_node_view_get_instance_private (view);
+
+ if (gtk_render_node_view_has_viewport (view))
+ {
+ *viewport = priv->viewport;
+ }
+ else if (priv->render_node != NULL)
+ {
+ graphene_rect_t bounds;
+
+ gsk_render_node_get_bounds (priv->render_node, &bounds);
+
+ viewport->x = bounds.origin.x;
+ viewport->y = bounds.origin.y;
+ viewport->width = bounds.size.width;
+ viewport->height = bounds.size.height;
+ }
+ else
+ {
+ *viewport = (GdkRectangle) { 0, 0, 0, 0 };
+ }
+}
+
+static void
+gtk_render_node_view_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkRenderNodeView *view = GTK_RENDER_NODE_VIEW (object);
+ GtkRenderNodeViewPrivate *priv = gtk_render_node_view_get_instance_private (view);
+
+ switch (param_id)
+ {
+ case PROP_VIEWPORT:
+ if (gtk_render_node_view_has_viewport (view))
+ g_value_set_boxed (value, &priv->viewport);
+ else
+ g_value_set_boxed (value, NULL);
+ break;
+
+ case PROP_RENDER_NODE:
+ g_value_set_pointer (value, priv->render_node);
+ break;
+
+ case PROP_CLIP_REGION:
+ g_value_set_boxed (value, priv->clip_region);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_render_node_view_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkRenderNodeView *view = GTK_RENDER_NODE_VIEW (object);
+
+ switch (param_id)
+ {
+ case PROP_VIEWPORT:
+ gtk_render_node_view_set_viewport (view, g_value_get_boxed (value));
+ break;
+
+ case PROP_RENDER_NODE:
+ gtk_render_node_view_set_render_node (view, g_value_get_pointer (value));
+ break;
+
+ case PROP_CLIP_REGION:
+ gtk_render_node_view_set_clip_region (view, g_value_get_boxed (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_render_node_view_dispose (GObject *object)
+{
+ GtkRenderNodeView *view = GTK_RENDER_NODE_VIEW (object);
+ GtkRenderNodeViewPrivate *priv = gtk_render_node_view_get_instance_private (view);
+
+ g_clear_pointer (&priv->render_node, gsk_render_node_unref);
+ g_clear_pointer (&priv->clip_region, cairo_region_destroy);
+
+ G_OBJECT_CLASS (gtk_render_node_view_parent_class)->dispose (object);
+}
+
+static void
+gtk_render_node_view_measure (GtkWidget *widget,
+ GtkOrientation orientation,
+ int for_size,
+ int *minimum,
+ int *natural,
+ int *minimum_baseline,
+ int *natural_baseline)
+{
+ GtkRenderNodeView *view = GTK_RENDER_NODE_VIEW (widget);
+ GtkRenderNodeViewPrivate *priv = gtk_render_node_view_get_instance_private (view);
+ GdkRectangle viewport;
+
+ *minimum = 1;
+
+ if (priv->render_node == NULL)
+ {
+ *natural = *minimum;
+ return;
+ }
+
+ gtk_render_node_view_get_effective_viewport (view, &viewport);
+ if (for_size < 0)
+ {
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ *natural = viewport.width;
+ else
+ *natural = viewport.height;
+ }
+ else
+ {
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ if (for_size > viewport.height)
+ *natural = viewport.width;
+ else
+ *natural = ceil ((double) for_size * viewport.width / viewport.height);
+ }
+ else
+ {
+ if (for_size > viewport.width)
+ *natural = viewport.height;
+ else
+ *natural = ceil ((double) for_size * viewport.height / viewport.width);
+ }
+ }
+}
+
+static GskRenderNode *
+gtk_render_node_view_real_get_render_node (GtkWidget *widget,
+ GskRenderer *renderer)
+{
+ GtkRenderNodeView *view = GTK_RENDER_NODE_VIEW (widget);
+ GtkRenderNodeViewPrivate *priv = gtk_render_node_view_get_instance_private (view);
+ GdkRectangle viewport;
+ graphene_rect_t rect;
+ GskRenderNode *node;
+ GskRenderer *fallback;
+ int width, height;
+ cairo_t *cr;
+
+ if (priv->render_node == NULL)
+ return FALSE;
+
+ gtk_render_node_view_get_effective_viewport (view, &viewport);
+ width = gtk_widget_get_allocated_width (widget);
+ height = gtk_widget_get_allocated_height (widget);
+
+ node = gsk_renderer_create_render_node (renderer);
+ gsk_render_node_set_name (node, "RenderNodeView node");
+ graphene_rect_init (&rect, 0, 0, width, height);
+ gsk_render_node_set_bounds (node, &rect);
+
+ cr = gsk_render_node_get_draw_context (node, renderer);
+ cairo_translate (cr, width / 2.0, height / 2.0);
+ if (width < viewport.width || height < viewport.height)
+ {
+ double scale = MIN ((double) width / viewport.width, (double) height / viewport.height);
+ cairo_scale (cr, scale, scale);
+ }
+ cairo_translate (cr, - viewport.x - viewport.width / 2.0, - viewport.y - viewport.height / 2.0);
+
+ fallback = gsk_renderer_create_fallback (renderer,
+ &(graphene_rect_t)
+ GRAPHENE_RECT_INIT (viewport.x, viewport.y,
+ viewport.width, viewport.height),
+ cr);
+ gsk_renderer_render (fallback, priv->render_node, NULL);
+ g_object_unref (fallback);
+
+ if (priv->clip_region)
+ {
+ cairo_region_t *draw;
+
+ draw = cairo_region_create_rectangle (&viewport);
+ cairo_region_subtract (draw, priv->clip_region);
+
+ cairo_set_source_rgba (cr, 0, 0, 0, 0.5);
+ gdk_cairo_region (cr, draw);
+ cairo_fill (cr);
+
+ cairo_region_destroy (draw);
+ }
+
+ cairo_destroy (cr);
+
+ return node;
+}
+
+static void
+gtk_render_node_view_class_init (GtkRenderNodeViewClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = gtk_render_node_view_get_property;
+ object_class->set_property = gtk_render_node_view_set_property;
+ object_class->dispose = gtk_render_node_view_dispose;
+
+ widget_class->measure = gtk_render_node_view_measure;
+ widget_class->get_render_node = gtk_render_node_view_real_get_render_node;
+
+ props[PROP_VIEWPORT] =
+ g_param_spec_boxed ("viewport",
+ "Viewport",
+ "Viewport",
+ CAIRO_GOBJECT_TYPE_RECTANGLE_INT,
+ G_PARAM_READWRITE);
+
+ props[PROP_RENDER_NODE] =
+ g_param_spec_pointer ("render-node",
+ "Render node",
+ "Render node",
+ /* GSK_TYPE_RENDER_NODE, */
+ G_PARAM_READWRITE);
+
+ props[PROP_CLIP_REGION] =
+ g_param_spec_boxed ("clip-region",
+ "Clip region",
+ "Clip region",
+ CAIRO_GOBJECT_TYPE_REGION,
+ G_PARAM_READWRITE);
+
+ g_object_class_install_properties (object_class, LAST_PROP, props);
+
+}
+
+static void
+gtk_render_node_view_init (GtkRenderNodeView *view)
+{
+ gtk_widget_set_has_window (GTK_WIDGET (view), FALSE);
+}
+
+GtkWidget *
+gtk_render_node_view_new (void)
+{
+ return g_object_new (GTK_TYPE_RENDER_NODE_VIEW, NULL);
+}
+
+void
+gtk_render_node_view_set_render_node (GtkRenderNodeView *view,
+ GskRenderNode *node)
+{
+ GtkRenderNodeViewPrivate *priv = gtk_render_node_view_get_instance_private (view);
+
+ if (priv->render_node == node)
+ return;
+
+ g_clear_pointer (&priv->render_node, gsk_render_node_unref);
+ if (node)
+ priv->render_node = gsk_render_node_ref (node);
+
+ if (gtk_render_node_view_has_viewport (view))
+ gtk_widget_queue_draw (GTK_WIDGET (view));
+ else
+ gtk_widget_queue_resize (GTK_WIDGET (view));
+
+ g_object_notify_by_pspec (G_OBJECT (view), props[PROP_RENDER_NODE]);
+}
+
+GskRenderNode *
+gtk_render_node_view_get_render_node (GtkRenderNodeView *view)
+{
+ GtkRenderNodeViewPrivate *priv = gtk_render_node_view_get_instance_private (view);
+
+ return priv->render_node;
+}
+
+void
+gtk_render_node_view_set_viewport (GtkRenderNodeView *view,
+ const GdkRectangle *viewport)
+{
+ GtkRenderNodeViewPrivate *priv = gtk_render_node_view_get_instance_private (view);
+
+ if (viewport)
+ {
+ priv->viewport = *viewport;
+ }
+ else
+ {
+ priv->viewport = (GdkRectangle) { 0, 0, 0, 0 };
+ }
+
+ gtk_widget_queue_resize (GTK_WIDGET (view));
+
+ g_object_notify_by_pspec (G_OBJECT (view), props[PROP_VIEWPORT]);
+}
+
+void
+gtk_render_node_view_get_viewport (GtkRenderNodeView *view,
+ GdkRectangle *viewport)
+{
+ GtkRenderNodeViewPrivate *priv = gtk_render_node_view_get_instance_private (view);
+
+ *viewport = priv->viewport;
+}
+
+void
+gtk_render_node_view_set_clip_region (GtkRenderNodeView *view,
+ const cairo_region_t *clip)
+{
+ GtkRenderNodeViewPrivate *priv = gtk_render_node_view_get_instance_private (view);
+
+ if (priv->clip_region)
+ cairo_region_destroy (priv->clip_region);
+ priv->clip_region = cairo_region_copy (clip);
+
+ gtk_widget_queue_draw (GTK_WIDGET (view));
+
+ g_object_notify_by_pspec (G_OBJECT (view), props[PROP_CLIP_REGION]);
+}
+
+const cairo_region_t*
+gtk_render_node_view_get_clip_region (GtkRenderNodeView *view)
+{
+ GtkRenderNodeViewPrivate *priv = gtk_render_node_view_get_instance_private (view);
+
+ return priv->clip_region;
+}
+
+
+// vim: set et sw=2 ts=2:
--- /dev/null
+/*
+ * Copyright (c) 2016 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _GTK_RENDER_NODE_VIEW_H_
+#define _GTK_RENDER_NODE_VIEW_H_
+
+#include <gtk/gtkbin.h>
+
+#define GTK_TYPE_RENDER_NODE_VIEW (gtk_render_node_view_get_type())
+#define GTK_RENDER_NODE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_RENDER_NODE_VIEW, GtkRenderNodeView))
+#define GTK_RENDER_NODE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_RENDER_NODE_VIEW, GtkRenderNodeViewClass))
+#define GTK_IS_RENDER_NODE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_RENDER_NODE_VIEW))
+#define GTK_IS_RENDER_NODE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_RENDER_NODE_VIEW))
+#define GTK_RENDER_NODE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_RENDER_NODE_VIEW, GtkRenderNodeViewClass))
+
+
+typedef struct _GtkRenderNodeView
+{
+ GtkWidget parent;
+} GtkRenderNodeView;
+
+typedef struct _GtkRenderNodeViewClass
+{
+ GtkWidgetClass parent;
+} GtkRenderNodeViewClass;
+
+G_BEGIN_DECLS
+
+GType gtk_render_node_view_get_type (void);
+
+GtkWidget * gtk_render_node_view_new (void);
+
+void gtk_render_node_view_set_render_node (GtkRenderNodeView *view,
+ GskRenderNode *node);
+GskRenderNode * gtk_render_node_view_get_render_node (GtkRenderNodeView *view);
+void gtk_render_node_view_set_viewport (GtkRenderNodeView *view,
+ const GdkRectangle *viewport);
+void gtk_render_node_view_get_viewport (GtkRenderNodeView *view,
+ GdkRectangle *viewport);
+void gtk_render_node_view_set_clip_region (GtkRenderNodeView *view,
+ const cairo_region_t *clip);
+const cairo_region_t*
+ gtk_render_node_view_get_clip_region (GtkRenderNodeView *view);
+
+
+G_END_DECLS
+
+#endif // _GTK_RENDER_NODE_VIEW_H_
+
+// vim: set et sw=2 ts=2: